/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkStateGridB.h"
#include "MkSdp/MkSdp.h"
#include "MkEvent/MkTimer.h"
#include "MkUtil/MkUtil.h"
#include "MkUtil/MkLog.h"
#include <tinyxml2.h>

CMkStateGridB::CMkStateGridB(CMkEventPool* pEventPool, CMkTimer* pTimer)
    : CMkSipServer(pEventPool, pTimer)
{

}

Uint32 CMkStateGridB::Start(const MkStateGridBStartParam& Param, const MkStateGridBRequestCallback& ReqCb)
{
    Uint32 ErrorCode = NoneError;
    if (!ReqCb) {
        return InvalidParams;
    }
    ErrorCode = CMkSipServer::Start(Param.SipId, Param.SipRealm, Param.LocalHost, Param.LocalPort, Param.MappingHost, Param.MappingPort, Param.LocalHost, Param.LocalPort, Param.MappingHost, Param.MappingPort);
    MkCheckErrorLog(ErrorCode, "start mk gb server id:%s on local port(%s:%d) mapping port(%s:%d) failed\n", Param.SipId.c_str(), Param.LocalHost.c_str(), Param.LocalPort, Param.MappingHost.c_str(), Param.MappingPort);

    m_Callback = ReqCb;
    m_RegisterExpries = Param.RegisterExpires;
    m_SubscribeExpires = Param.SubscribeExpires;
    MkInfoLog("start state grid a server success\n");
    return NoneError;
}

Uint32 CMkStateGridB::Stop()
{
    return CMkSipServer::Stop();
}

Uint32 CMkStateGridB::AddRouter(const MkString& RouterId, const MkString& Realm, const MkString& RemoteIp, Uint16 RemotePort, BOOL bTcp)
{
    MkStateGridBRouter Router;
    Router.Id = RouterId;
    Router.Realm = Realm;
    Router.Host = RemoteIp;
    Router.Port = RemotePort;
    Router.bTcp = bTcp;
    m_RouterLock.WLock();
    m_MapGbRouter[RouterId] = Router;
    m_RouterLock.WUnlock();
    return NoneError;
}

Uint32 CMkStateGridB::RegisterServer(const MkString& ServerId, Uint32 Expires, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(ServerId, Router);
    MkCheckErrorLog(ErrorCode, "dst id:%s not found\n", ServerId.c_str());
    MkMapString ExternHeader;
    ExternHeader["Expires"] = std::to_string(Expires);

    return SendSipRequest(ServerId, ServerId, Router.Realm, MkSipMethodRegister, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, ExternHeader, MkSipContentNone, "", "");
}

Uint32 CMkStateGridB::RegisterServerWithRegisterId(const MkString& RegisterId, Uint32 Expires, const MkMapString& AuthorizationParam, const MkStateGridBResponseCallback& ResCb)
{
    MkMapString ExternHeader;
    ExternHeader["Expires"] = std::to_string(Expires);
    MkString strAuthorization;
    if (!AuthorizationParam.empty()) {
        strAuthorization = "Digest ";
    }

    MkMapString::const_iterator it = AuthorizationParam.begin();
    for (; it != AuthorizationParam.end(); it++) {
        if (it != AuthorizationParam.begin()) {
            strAuthorization += ", ";
        }
        strAuthorization += it->first + "=" + it->second;
    }
    if (!strAuthorization.empty()) {
        ExternHeader["Authorization"] = strAuthorization;
    }

    return Register(RegisterId, ExternHeader, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    });
}

Uint32 CMkStateGridB::GetResourse(const MkString& RouterId, const MkString& DstId, Uint32 FromIndex, Uint32 ToIndex, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());
    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Request_Resource");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
    ItemNode->SetAttribute("Code", DstId.c_str());
    ItemNode->SetAttribute("UserCode", GetSipId().c_str());
    ItemNode->SetAttribute("FromIndex", FromIndex);
    ItemNode->SetAttribute("ToIndex", ToIndex);
    root->InsertEndChild(ItemNode);
    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    MkString strXml = printer.CStr();

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodMessage, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, MkMapString(), MkSipContentXml, strXml, "");
}

Uint32 CMkStateGridB::GetHistoryAlarm(const MkString& RouterId, const MkString& DstId, Uint32 AlarmType, const CMkTime& BeginTime, const CMkTime& EndTime, Uint32 Level, Uint32 FromIndex, Uint32 ToIndex, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());
    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Request_History_Alarm");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
    ItemNode->SetAttribute("Code", DstId.c_str());
    ItemNode->SetAttribute("UserCode", GetSipId().c_str());
    ItemNode->SetAttribute("Type", AlarmType);
    MkString strBeginTime;
    MkString strEndTime;
    BeginTime.GetString(strBeginTime, "T", "Z");
    EndTime.GetString(strEndTime, "T", "Z");
    ItemNode->SetAttribute("BeginTime", strBeginTime.c_str());
    ItemNode->SetAttribute("EndTime", strEndTime.c_str());
    ItemNode->SetAttribute("Level", Level);
    ItemNode->SetAttribute("FromIndex", FromIndex);
    ItemNode->SetAttribute("ToIndex", ToIndex);
    root->InsertEndChild(ItemNode);
    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    MkString strXml = printer.CStr();

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodMessage, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, MkMapString(), MkSipContentXml, strXml, "");
}

Uint32 CMkStateGridB::FindRecord(const MkString& RouterId, const MkString& DstId, const MkStateGridBRecordType& RecordType, const CMkTime& BeginTime, const CMkTime& EndTime, Uint32 FromIndex, Uint32 ToIndex, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());
    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Request_History_Video");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
    ItemNode->SetAttribute("Code", DstId.c_str());
    ItemNode->SetAttribute("UserCode", GetSipId().c_str());
    ItemNode->SetAttribute("Type", RecordType);
    MkString strBeginTime;
    MkString strEndTime;
    BeginTime.GetString(strBeginTime, "T", "Z");
    EndTime.GetString(strEndTime, "T", "Z");
    ItemNode->SetAttribute("BeginTime", strBeginTime.c_str());
    ItemNode->SetAttribute("EndTime", strEndTime.c_str());
    ItemNode->SetAttribute("FromIndex", FromIndex);
    ItemNode->SetAttribute("ToIndex", ToIndex);
    root->InsertEndChild(ItemNode);
    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    MkString strXml = printer.CStr();

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodMessage, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, MkMapString(), MkSipContentXml, strXml, "");
}

Uint32 CMkStateGridB::InviteStream(const MkString& RouterId, const MkString& DstId, const MkString& OfferSdp, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodInvite, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, MkMapString(), MkSipContentSdp, OfferSdp, "");
}

Uint32 CMkStateGridB::PtzControl(const MkString& RouterId, const MkString& DstId, const MkStateGridPtzCommandType& Cmd, Uint32 Param1, Uint32 Param2, Uint32 Param3, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    MkString strXml;
    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());

    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Control_Camera");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
    ItemNode->SetAttribute("Command", std::to_string(Cmd).c_str());
    ItemNode->SetAttribute("CommandPara1", std::to_string(Cmd).c_str());
    ItemNode->SetAttribute("CommandPara2", std::to_string(Cmd).c_str());
    ItemNode->SetAttribute("CommandPara3", std::to_string(Cmd).c_str());
    root->InsertEndChild(ItemNode);
    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    strXml = printer.CStr();

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodMessage, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, MkMapString(), MkSipContentXml, strXml, "");
}

Uint32 CMkStateGridB::EventSubscribe(const MkString& RouterId, const MkString& DstId, Uint32 Expires, const MkStateGridBSubscribeType& SubscribeType, const MkMap<MkString, Uint32>& MapSubId, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    MkString strXml;
    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());

    MkMapString ExternHeader;

    ExternHeader["Expires"] = std::to_string(Expires);

    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    if (MkStateGridBSubscribeAlarm == SubscribeType) {
        MkMap<MkString, Uint32>::const_iterator it = MapSubId.begin();
        for (; it != MapSubId.end(); it++) {
            tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
            ItemNode->SetAttribute("Code", it->first.c_str());
            ItemNode->SetAttribute("Type", std::to_string(it->second).c_str());
            root->InsertEndChild(ItemNode);
        }
        ExternHeader["Event"] = "alarm";
        root->SetAttribute("EventType", "Subscribe_Alarm");
    } else {
        MkMap<MkString, Uint32>::const_iterator it = MapSubId.begin();
        for (; it != MapSubId.end(); it++) {
            tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
            ItemNode->SetAttribute("Code", it->first.c_str());
            root->InsertEndChild(ItemNode);
        }
        ExternHeader["Event"] = "presence";
        root->SetAttribute("EventType", "Subscribe_Status");
    }
    doc.InsertEndChild(root);

    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    strXml = printer.CStr();

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodSubscribe, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, ExternHeader, MkSipContentXml, strXml, "");
}

Uint32 CMkStateGridB::StopEventSubscirbe(const MkString& SubscribeId, const MkStateGridBSubscribeType& SubscribeType, const MkStateGridBResponseCallback& ResCb)
{
    MkMapString OtherHeaders;
    OtherHeaders["Expires"] = "0";
    OtherHeaders["Event"] = MkStateGridBSubscribeAlarm == SubscribeType ? "alarm" : "presence";
    return StopSubscribe(SubscribeId, OtherHeaders, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    });
}

Uint32 CMkStateGridB::ByeStream(const MkString& SessionId, const MkStateGridBResponseCallback& ResCb)
{
    return StopCall(SessionId, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    });
}

Uint32 CMkStateGridB::AlarmNotify(const MkString& SubId, const MkString& StrState, const MkString& Code, const MkString& Name, const Uint32 AlarmType, const CMkTime& StartTime, const CMkTime& EndTime, const MkStateGridBResponseCallback& ResCb)
{
    MkString strXml;
    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());

    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Notify_Alarm");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
    ItemNode->SetAttribute("Code", Code.c_str());
    ItemNode->SetAttribute("Name", Name.c_str());
    ItemNode->SetAttribute("Type", std::to_string(AlarmType).c_str());
    MkString strStartTime;
    StartTime.GetString(strStartTime, "T", "Z");
    ItemNode->SetAttribute("StartTime", strStartTime.c_str());
    if (!EndTime.IsEmpty()) {
        MkString strEndTime;
        EndTime.GetString(strEndTime, "T", "Z");
        ItemNode->SetAttribute("EndTime", strEndTime.c_str());
    }
    root->InsertEndChild(ItemNode);

    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    strXml = printer.CStr();

    return SubscribeNotify(SubId, "alarm", StrState, MkMapString(), MkSipContentXml, strXml, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    });
}

Uint32 CMkStateGridB::StateNotify(const MkString& SubId, const MkString& StrState, const MkString& Code, const MkString& Name, Uint32 Status, const MkStateGridBResponseCallback& ResCb)
{
    MkString strXml;
    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());

    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Notify_Status");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
    ItemNode->SetAttribute("Code", Code.c_str());
    ItemNode->SetAttribute("Name", Name.c_str());
    ItemNode->SetAttribute("Status", std::to_string(Status).c_str());
    root->InsertEndChild(ItemNode);

    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    strXml = printer.CStr();

    return SubscribeNotify(SubId, "presence", StrState, MkMapString(), MkSipContentXml, strXml, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    });
}

Uint32 CMkStateGridB::ResourcePush(const MkString& RouterId, const MkString& DstId, const MkString& ParentId, const MkMapStateGridBResourse& MapResource, const MkStateGridBResponseCallback& ResCb)
{
    MkStateGridBRouter Router;
    Uint32 ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "router:%s find failed\n", RouterId.c_str());

    MkString strXml;
    tinyxml2::XMLDocument doc;
    doc.InsertFirstChild(doc.NewDeclaration());

    tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
    root->SetAttribute("EventType", "Push_Resourse");
    doc.InsertEndChild(root);

    tinyxml2::XMLElement *CodeElement = doc.NewElement("Code");
    CodeElement->InsertFirstChild(doc.NewText(ParentId.c_str()));
    root->InsertEndChild(CodeElement);

    tinyxml2::XMLElement *SubListElement = doc.NewElement("SubList");
    SubListElement->SetAttribute("SubNum", static_cast<int>(MapResource.size()));

    MkMapStateGridBResourse::const_iterator it = MapResource.begin();
    for (; it != MapResource.end(); it++) {
        tinyxml2::XMLElement *ItemElement = doc.NewElement("Item");
        ItemElement->SetAttribute("Code", it->second.Code.c_str());
        ItemElement->SetAttribute("Name", it->second.Name.c_str());
        ItemElement->SetAttribute("Status", it->second.Status);
        ItemElement->SetAttribute("DecoderTag", it->second.DecodeTag);
        ItemElement->SetAttribute("Longitude", it->second.Longitude);
        ItemElement->SetAttribute("Latitude", it->second.Latitude);
        ItemElement->SetAttribute("SubNum", it->second.SubNum);
        SubListElement->InsertEndChild(ItemElement);
    }

    root->InsertEndChild(SubListElement);
    tinyxml2::XMLPrinter printer;
    doc.Print(&printer);
    strXml = printer.CStr();

    return SendSipRequest(RouterId, DstId, Router.Realm, MkSipMethodNotify, Router.Host, Router.Port, Router.bTcp, [this, ResCb](const CMkSipMessage& SipMessage) {
        AddReqeust(SipMessage.GetTransactionId(), ResCb);
    }, MkMapString(), MkSipContentXml, strXml);
}

Uint32 CMkStateGridB::OnSipRequest(const MkSipRequestEvent& RequestEvent, const CMkSipMessage& SipRequest, const EventRequestCallback& Cb)
{
    Uint32 ErrorCode = NoneError;
    switch (RequestEvent) {
    case MkSipRequestRegister:
        ErrorCode = RegisterRequestParse(SipRequest, Cb);
        break;
    case MkSipRequestMessage:
        ErrorCode = MessageRequestParse(SipRequest, Cb);
        break;
    case MkSipRequestNotify:
        ErrorCode = NotifyRequestParse(SipRequest, Cb);
        break;
    case MkSipRequestInvite:
        ErrorCode = InviteRequestParse(SipRequest, Cb);
        break;
    case MkSipRequestSubscribe:
        ErrorCode = SubscribeRequestParse(SipRequest, Cb);
        break;
    case MkSipRequestSubscribeNotify:
        ErrorCode = SubscribeNotifyRequestParse(SipRequest, Cb);
        break;
    case MkSipRequestBye:
        ByeParse(SipRequest, Cb);
        break;
    default:
        break;
    }
    if (NoneError != ErrorCode) {
        Cb(MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
    }
    return NoneError;
}

Uint32 CMkStateGridB::OnSipResponse(const MkSipResponseEvent& ResponseEvent, const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse, const EventResponseCallback& Cb)
{
    MkDebugLog("on sip response event:%d transaction:%s status:%d\n", ResponseEvent, TransActionId.c_str(), SipResponse.GetStatusCode());
    if (MkSipResponseRegister == ResponseEvent) {
        return RegisterResponseParse(TransActionId, SipRequest, SipResponse);
    }
    Uint32 ErrorCode = NoneError;
    if (MkSipStatusOK != SipResponse.GetStatusCode()) {
        MkErrorLog("transaction:%s response:%d\n", TransActionId.c_str(), SipResponse.GetStatusCode());
        ResponseCallback(SystemError, TransActionId, nullptr);
        return SystemError;
    }
    switch (ResponseEvent) {
    case MkSipResponseMessage:
        ErrorCode = MessageResponseParse(TransActionId, SipRequest, SipResponse);
        break;
    case MkSipResponseInvite:
        ErrorCode = InviteResponseParse(TransActionId, SipRequest, SipResponse, Cb);
        break;
    case MkSipResponseSubscribe:
        ErrorCode = SubscribeResponseParse(TransActionId, SipRequest, SipResponse);
        break;
    case MkSipResponseNotify:
    case MkSipResponseBye:
    case MkSipResponseSubscribeNotify:
        ResponseCallback(NoneError, TransActionId, nullptr);
        break;
    default:
        ErrorCode = UnSupported;
        break;
    }
    if (NoneError != ErrorCode) {
        ResponseCallback(SystemError, TransActionId, nullptr);
    }
    return ErrorCode;
}

Uint32 CMkStateGridB::RegisterRequestParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    if (SipRequest.GetVecAuthorization().empty()) {
        MkMapString ExternHeaders;
        MkString Nonce;
        CMkUtil::CreateRandomString(16, Nonce);
        MkString WWW_Authenticate = "Digest realm=\"" + GetRealm() + "\",algorithm=MD5,nonce=\"" + Nonce + "\",stale=false";
        ExternHeaders["WWW-Authenticate"] = WWW_Authenticate;
        EventCallback(MkSipStatusUnauthorized, ExternHeaders, MkSipContentNone, "");
        return NoneError;
    }
    Uint32 ErrorCode = NoneError;
    CMkSipFrom SipFrom = SipRequest.GetFrom();
    MkString RouterId = SipFrom.GetUri().GetUserName();
    MkString DeviceRealm;
    if (0 == SipFrom.GetUri().GetPort()) {
        DeviceRealm = SipFrom.GetUri().GetHost();
    }
    CMkSipAuthorization SipAuthorization = *(SipRequest.GetVecAuthorization()).begin();
    MkString UserName;
    MkString Realm;
    MkString Nonce;
    MkString Uri;
    MkString Response;
    MkString Algorithm;
    ErrorCode = SipAuthorization.GetParam("username", UserName);
    MkCheckErrorLog(ErrorCode, "get value failed\n");
    ErrorCode = SipAuthorization.GetParam("realm", Realm);
    MkCheckErrorLog(ErrorCode, "get value failed\n");
    ErrorCode = SipAuthorization.GetParam("nonce", Nonce);
    MkCheckErrorLog(ErrorCode, "get value failed\n");
    ErrorCode = SipAuthorization.GetParam("uri", Uri);
    MkCheckErrorLog(ErrorCode, "get value failed\n");
    ErrorCode = SipAuthorization.GetParam("response", Response);
    MkCheckErrorLog(ErrorCode, "get value failed\n");
    ErrorCode = SipAuthorization.GetParam("algorithm", Algorithm);
    MkCheckErrorLog(ErrorCode, "get value failed\n");

    MkString StrExpries;
    Uint32 uExpires = 0;
    ErrorCode = SipRequest.GetHeaderValue("Expires", StrExpries);
    if (NoneError == ErrorCode) {
        uExpires = std::stoi(StrExpries);
        if (0 != uExpires) {
            if (uExpires > m_RegisterExpries) {
                uExpires = m_RegisterExpries;
            }
        }
    } else { //not has expires header set defalut
        uExpires = m_RegisterExpries;
    }

    CMkStateGridBRegisterRequest Msg(RouterId, RouterId, SipRequest.GetRemoteHost(), SipRequest.GetRemotePort(), SipAuthorization.GetAuthType(), UserName, Realm, Nonce, Uri, Response, Algorithm, uExpires);
    if (nullptr != m_Callback) {
        m_Callback(&Msg, [this, RouterId, DeviceRealm, SipRequest, uExpires, EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pRes) {
            MkDebugLog("return register callback error code:%d\n", ErrorCode);
            if (NoneError != ErrorCode) {
                EventCallback(MkSipStatusNotFound, MkMapString(), MkSipContentNone, "");
            } else {
                MkString strNowTime;
                NowMkTime.GetString(strNowTime, "T", "", TRUE);
                MkMapString MapAddHeader;
                MapAddHeader.insert(std::pair<MkString, MkString>("Date", strNowTime));
                MapAddHeader.insert(std::pair<MkString, MkString>("Expires", std::to_string(uExpires)));
                MkDebugLog("register success\n");
                EventCallback(MkSipStatusOK, MapAddHeader, MkSipContentNone, "");
                if (0 == uExpires) {
                    DeleteRouter(RouterId);
                } else {
                    AddRouter(RouterId, DeviceRealm, SipRequest.GetRemoteHost(), SipRequest.GetRemotePort(), SipRequest.IsTcp());
                }
            }
        });
    } else {
        EventCallback(MkSipStatusNotFound, MkMapString(), MkSipContentNone, "");
    }
    return NoneError;
}

Uint32 CMkStateGridB::NotifyRequestParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    MkString RouterId = SipRequest.GetFrom().GetUri().GetUserName();
    MkDebugLog("get router id:%s\n", RouterId.c_str());
    Uint32 ErrorCode = NoneError;
    MkStateGridBRouter Router;
    ErrorCode = GetRouter(RouterId, Router);
    MkCheckErrorLog(ErrorCode, "get router id:%s failed\n", RouterId.c_str());
    ErrorCode = NotifyRequestXmlParse(SipRequest.GetBody(), RouterId, EventCallback);
    MkCheckErrorLog(ErrorCode, "noti request parse failed\n");
    return NoneError;
}

Uint32 CMkStateGridB::NotifyRequestXmlParse(const MkString& XmlBody, const MkString& RouterId, const EventRequestCallback& EventCallback)
{
    tinyxml2::XMLDocument doc;
    Uint32 ErrorCode = doc.Parse(XmlBody.c_str());
    if (tinyxml2::XML_SUCCESS != ErrorCode) {
        MkErrorLog("notify request body:%s parse failed\n", XmlBody.c_str());
        return InvalidParams;
    }
    tinyxml2::XMLElement *pRootElement = doc.FirstChildElement("SIP_XML");
    if (!pRootElement) {
        MkErrorLog("xmlBody:%s not has root sip_xml\n", XmlBody.c_str());
        return InvalidParams;
    }
    MkString EventType = pRootElement->Attribute("EventType");
    if ("Push_Resourse" == EventType) {
        ErrorCode = NotifyRequestResoursePushParse(pRootElement, RouterId, EventCallback);
    }
    return ErrorCode;
}

Uint32 CMkStateGridB::NotifyRequestResoursePushParse(const tinyxml2::XMLElement *pElement, const MkString& RouterId, const EventRequestCallback& EventCallback)
{
    const tinyxml2::XMLElement *pCodeElement = pElement->FirstChildElement("Code");
    if (!pCodeElement) {
        MkErrorLog("resource push not has code item\n");
        return InvalidParams;
    }
    MkString Code = CMkUtil::SafeMkString(pCodeElement->GetText());
    MkMapStateGridBResourse MapResourse;
    const tinyxml2::XMLElement *pSubListElement = pElement->FirstChildElement("SubList");
    if (!pSubListElement) {
        MkErrorLog("resouce push not has sublist item\n");
        return InvalidParams;
    }

    const tinyxml2::XMLElement *pItemElement = pSubListElement->FirstChildElement("Item");
    while (nullptr != pItemElement) {
        MkStateGridBResourseItem Item;
        Item.Code = CMkUtil::SafeMkString(pItemElement->Attribute("Code"));
        Item.Name = CMkUtil::SafeMkString(pItemElement->Attribute("Name"));
        Item.Status = CMkUtil::SafeAtoi(pItemElement->Attribute("Status"));
        Item.DecodeTag = CMkUtil::SafeAtoi(pItemElement->Attribute("DecoderTag"));
        Item.Longitude = static_cast<float>(CMkUtil::SafeAtof(pItemElement->Attribute("Longitude")));
        Item.Latitude = static_cast<float>(CMkUtil::SafeAtof(pItemElement->Attribute("Latitude")));
        Item.SubNum = CMkUtil::SafeAtoi(pItemElement->Attribute("SubNum"));
        MapResourse[Item.Code] = Item;
        pItemElement = pItemElement->NextSiblingElement();
    }
    CMkStateGridBResoursePushRequest Req(RouterId, RouterId, Code, MapResourse);
    if (m_Callback) {
        return m_Callback(&Req, [this, EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pRes) {
            EventCallback(NoneError == ErrorCode ? MkSipStatusOK : MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
        });
    }
    return InvalidParams;
}

Uint32 CMkStateGridB::RegisterResponseParse(const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse)
{
    MkVector<CMkSipWwwAuthenticate> VecWwwAuthen = SipResponse.GetVecWwwAuthenticate();
    if (!VecWwwAuthen.empty()) {
        CMkSipWwwAuthenticate Authen = *VecWwwAuthen.begin();
        MkString Realm;
        MkString Nonce;
        MkString Algorithm;
        Authen.GetParam("realm", Realm);
        Authen.GetParam("nonce", Nonce);
        Authen.GetParam("algorithm", Algorithm);
        CMkStateGridBRegisterResponse Res(SipRequest.GetUri().GetUserName(), SipRequest.GetUri().GetUserName(), SipRequest.GetDialogId(), SipResponse.GetStatusCode(), Realm, Nonce, Algorithm);
        ResponseCallback(NoneError, TransActionId, &Res);
    } else {
        MkString DateTime;
        SipResponse.GetHeaderValue("Date", DateTime);
        CMkStateGridBRegisterResponse Res(SipRequest.GetUri().GetUserName(), SipRequest.GetUri().GetUserName(), SipRequest.GetDialogId(), SipResponse.GetStatusCode(), "", "", "");
        ResponseCallback(NoneError, TransActionId, &Res);
    }
    return NoneError;
}

Uint32 CMkStateGridB::MessageResponseParse(const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse)
{
    MkString RouterId = SipRequest.GetFrom().GetUri().GetUserName();
    tinyxml2::XMLDocument doc;
    Uint32 ErrorCode = doc.Parse(SipResponse.GetBody().c_str());
    if (tinyxml2::XML_SUCCESS == ErrorCode) {
        tinyxml2::XMLElement *pRootElement = doc.FirstChildElement("SIP_XML");
        if (!pRootElement) {
            MkErrorLog("xmlBody:%s not has root sip_xml\n", SipResponse.GetBody().c_str());
            return InvalidParams;
        }
        MkString EventType = pRootElement->Attribute("EventType");
        if ("Response_Resource" == EventType) {
            ErrorCode = MessageResponseResourceParse(pRootElement, RouterId, TransActionId);
        } else if ("Response_History_Alarm" == EventType) {
            ErrorCode = MessageResponseHistoryAlarmParse(pRootElement, RouterId, TransActionId);
        } else if ("Response_History_Video" == EventType) {
            ErrorCode = MessageResponseHistoryRecordParse(pRootElement, RouterId, TransActionId);
        } else {
            ErrorCode = InvalidParams;
        }
    } else {
        ErrorCode = doc.Parse(SipRequest.GetBody().c_str());
        if (NoneError != ErrorCode) {
            return InvalidParams;
        }
        tinyxml2::XMLElement *pRootElement = doc.FirstChildElement("SIP_XML");
        if (!pRootElement) {
            MkErrorLog("xmlBody:%s not has root sip_xml\n", SipResponse.GetBody().c_str());
            return InvalidParams;
        }
        MkString EventType = pRootElement->Attribute("EventType");
        if ("Control_Camera" == EventType) {
            ErrorCode = NoneError;
            ResponseCallback(NoneError, TransActionId, nullptr);
        } else {
            ErrorCode = InvalidParams;
        }
    }
    return ErrorCode;
}

Uint32 CMkStateGridB::MessageResponseResourceParse(const tinyxml2::XMLElement *pElement, const MkString& RouterId, const MkString& TransActionId)
{
    const tinyxml2::XMLElement *pSubListElement = pElement->FirstChildElement("SubList");
    if (!pSubListElement) {
        return InvalidParams;
    }
    MkString Code = CMkUtil::SafeMkString(pSubListElement->Attribute("Code"));
    Uint32 RealNum = CMkUtil::SafeAtoi(pSubListElement->Attribute("RealNum"));
    Uint32 SubNum = CMkUtil::SafeAtoi(pSubListElement->Attribute("SubNum"));
    Uint32 FromIndex = CMkUtil::SafeAtoi(pSubListElement->Attribute("FromIndex"));
    Uint32 ToIndex = CMkUtil::SafeAtoi(pSubListElement->Attribute("ToIndex"));
    MkMapStateGridBResourse MapResourse;
    const tinyxml2::XMLElement *pItemElement = pSubListElement->FirstChildElement("Item");
    while (nullptr != pItemElement) {
        MkStateGridBResourseItem Item;
        Item.Code = CMkUtil::SafeMkString(pItemElement->Attribute("Code"));
        Item.Name = CMkUtil::SafeMkString(pItemElement->Attribute("Name"));
        Item.Status = CMkUtil::SafeAtoi(pItemElement->Attribute("Status"));
        Item.DecodeTag = CMkUtil::SafeAtoi(pItemElement->Attribute("DecoderTag"));
        Item.Longitude = static_cast<float>(CMkUtil::SafeAtof(pItemElement->Attribute("Longitude")));
        Item.Latitude = static_cast<float>(CMkUtil::SafeAtof(pItemElement->Attribute("Latitude")));
        Item.SubNum = CMkUtil::SafeAtoi(pItemElement->Attribute("SubNum"));
        MapResourse[Item.Code] = Item;
        pItemElement = pItemElement->NextSiblingElement();
    }
    CMkStateGridBGetResourceResponse Res(RouterId, RouterId, Code, RealNum, SubNum, FromIndex, ToIndex, MapResourse);
    return ResponseCallback(NoneError, TransActionId, &Res);
}

Uint32 CMkStateGridB::MessageResponseHistoryAlarmParse(const tinyxml2::XMLElement *pElement, const MkString& RouterId, const MkString& TransActionId)
{
    const tinyxml2::XMLElement *pSubListElement = pElement->FirstChildElement("SubList");
    if (!pSubListElement) {
        return InvalidParams;
    }
    Uint32 RealNum = CMkUtil::SafeAtoi(pSubListElement->Attribute("RealNum"));
    Uint32 SubNum = CMkUtil::SafeAtoi(pSubListElement->Attribute("SubNum"));
    Uint32 FromIndex = CMkUtil::SafeAtoi(pSubListElement->Attribute("FromIndex"));
    Uint32 ToIndex = CMkUtil::SafeAtoi(pSubListElement->Attribute("ToIndex"));
    MkVectorStateGridBAlarm VecAlarm;
    const tinyxml2::XMLElement *pItemElement = pSubListElement->FirstChildElement("Item");
    while (nullptr != pItemElement) {
        MkStateGridBAlarmItem Item;
        Item.Code = CMkUtil::SafeMkString(pItemElement->Attribute("Code"));
        Item.BeginTime = CMkTime(CMkUtil::SafeMkString(pItemElement->Attribute("BeginTime")), "T", "Z");
        Item.Status = CMkUtil::SafeAtoi(pItemElement->Attribute("Status"));
        Item.AlarmType = CMkUtil::SafeAtoi(pItemElement->Attribute("Type"));
        VecAlarm.push_back(Item);
        pItemElement = pItemElement->NextSiblingElement();
    }
    CMkStateGridBGetAlarmResponse Res(RouterId, RouterId, RealNum, SubNum, FromIndex, ToIndex, VecAlarm);
    return ResponseCallback(NoneError, TransActionId, &Res);
}

Uint32 CMkStateGridB::MessageResponseHistoryRecordParse(const tinyxml2::XMLElement *pElement, const MkString& RouterId, const MkString& TransActionId)
{
    const tinyxml2::XMLElement *pSubListElement = pElement->FirstChildElement("SubList");
    if (!pSubListElement) {
        return InvalidParams;
    }
    Uint32 RealNum = CMkUtil::SafeAtoi(pSubListElement->Attribute("RealNum"));
    Uint32 SubNum = CMkUtil::SafeAtoi(pSubListElement->Attribute("SubNum"));
    Uint32 FromIndex = CMkUtil::SafeAtoi(pSubListElement->Attribute("FromIndex"));
    Uint32 ToIndex = CMkUtil::SafeAtoi(pSubListElement->Attribute("ToIndex"));
    MkVectorStateGridBRecord VecAlarm;
    const tinyxml2::XMLElement *pItemElement = pSubListElement->FirstChildElement("Item");
    while (nullptr != pItemElement) {
        MkStateGridBRecordItem Item;
        Item.FileName = CMkUtil::SafeMkString(pItemElement->Attribute("FileName"));
        Item.BeginTime = CMkTime(CMkUtil::SafeMkString(pItemElement->Attribute("BeginTime")), "T", "Z");
        Item.EndTime = CMkTime(CMkUtil::SafeMkString(pItemElement->Attribute("EndTime")), "T", "Z");
        Item.FileSize = CMkUtil::SafeAtoi(pItemElement->Attribute("Size"));
        Item.DecoderTag = CMkUtil::SafeAtoi(pItemElement->Attribute("DecoderTag"));
        Item.RecordType = CMkUtil::SafeAtoi(pItemElement->Attribute("Type"));
        VecAlarm.push_back(Item);
        pItemElement = pItemElement->NextSiblingElement();
    }
    CMkStateGridBGetRecordResponse Res(RouterId, RouterId, RealNum, SubNum, FromIndex, ToIndex, VecAlarm);
    return ResponseCallback(NoneError, TransActionId, &Res);
}

Uint32 CMkStateGridB::InviteResponseParse(const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse, const EventResponseCallback& Cb)
{
    MkString SdpBody = SipResponse.GetBody();
    MkString RouterId = SipRequest.GetTo().GetUri().GetUserName();
    MkString DstId = SipRequest.GetUri().GetUserName();
    CMkStateGridBMediaResponse Res(RouterId, DstId, SipResponse.GetDialogId(), SdpBody, Cb);
    return ResponseCallback(NoneError, TransActionId, &Res);
}

Uint32 CMkStateGridB::SubscribeResponseParse(const MkString& TransActionId, const CMkSipMessage& SipRequest, const CMkSipMessage& SipResponse)
{
    MkString strValue = "0";
    SipResponse.GetHeaderValue("Expires", strValue);
    CMkStateGridBSubscribeResponse Res(SipRequest.GetTo().GetUri().GetUserName(), SipRequest.GetUri().GetUserName(), SipRequest.GetDialogId(), std::stoi(strValue));
    return ResponseCallback(NoneError, TransActionId, &Res);
}

Uint32 CMkStateGridB::MessageRequestParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    MkString strXml = SipRequest.GetBody();
    tinyxml2::XMLDocument doc;
    Uint32 ErrorCode = doc.Parse(strXml.c_str());
    if (tinyxml2::XML_SUCCESS != ErrorCode) {
        return ErrorCode;
    }
    tinyxml2::XMLElement *Element = doc.FirstChildElement("SIP_XML");
    if (!Element) {
        return SystemError;
    }
    MkString EventType = CMkUtil::SafeMkString(Element->Attribute("EventType"));
    tinyxml2::XMLElement *ItemNode = Element->FirstChildElement("Item");
    if (!ItemNode) {
        return SystemError;
    }
    if ("Control_Camera" == EventType) {
        CMkStateGridBPtzControlRequest Req(SipRequest.GetTo().GetUri().GetUserName(), SipRequest.GetUri().GetUserName(), CMkUtil::SafeAtoi(ItemNode->Attribute("Command")), CMkUtil::SafeAtoi(ItemNode->Attribute("CommandPara1")), CMkUtil::SafeAtoi(ItemNode->Attribute("CommandPara2")), CMkUtil::SafeAtoi(ItemNode->Attribute("CommandPara3")));
        ErrorCode = m_Callback(&Req, [EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
            EventCallback(NoneError == ErrorCode ? MkSipStatusOK : MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
        });
    } else if ("Request_Resource" == EventType) {
        ErrorCode = MessageGetResouceRequestParse(SipRequest.GetTo().GetUri().GetUserName(), ItemNode, EventCallback);
    } else if ("Request_History_Video" == EventType) {
        ErrorCode = MessageGetRecordRequestParse(SipRequest.GetTo().GetUri().GetUserName(), ItemNode, EventCallback);
    } else if ("Request_History_Alarm" == EventType) {
        ErrorCode = MessageGetAlarmRequestParse(SipRequest.GetTo().GetUri().GetUserName(), ItemNode, EventCallback);
    }
    return ErrorCode;
}

Uint32 CMkStateGridB::SubscribeRequestParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    MkString strEvent;
    MkString strExpires;
    Uint32 Expires = 3600;
    Uint32 ErrorCode = SipRequest.GetHeaderValue("Event", strEvent);
    MkCheckErrorLog(ErrorCode, "get event header failed\n");

    ErrorCode = SipRequest.GetHeaderValue("Expires", strExpires);
    if (NoneError == ErrorCode) {
        Expires = stoi(strExpires);
    }
    MkString strXml = SipRequest.GetBody();
    tinyxml2::XMLDocument doc;
    ErrorCode = doc.Parse(strXml.c_str());
    if (tinyxml2::XML_SUCCESS != ErrorCode) {
        return ErrorCode;
    }
    tinyxml2::XMLElement *Element = doc.FirstChildElement("SIP_XML");
    if (!Element) {
        return SystemError;
    }
    MkMap<MkString, Uint32> MapCode;
    MkString EventType = CMkUtil::SafeMkString(Element->Attribute("EventType"));
    tinyxml2::XMLElement *ItemNode = Element->FirstChildElement("Item");
    while (ItemNode) {
        MapCode[CMkUtil::SafeMkString(ItemNode->Attribute("Code"))] = CMkUtil::SafeAtoi(ItemNode->Attribute("Type"));
        ItemNode = ItemNode->NextSiblingElement();
    }

    CMkStateGridBSubscribeRequest Req(SipRequest.GetTo().GetUri().GetUserName(), SipRequest.GetUri().GetUserName(), SipRequest.GetDialogId(), "Subscribe_Alarm" == EventType ? MkStateGridBSubscribeAlarm : MkStateGridBSubscribeStatus, Expires, MapCode);

    return m_Callback(&Req, [this, EventType, EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
        const  CMkStateGridBSubscribeResponse* pSubRes = dynamic_cast<const CMkStateGridBSubscribeResponse*>(pResBase);
        if (!pSubRes || NoneError != ErrorCode) {
            EventCallback(MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
            return;
        }
        MkMapString ExternHeads;
        ExternHeads["Expires"] = std::to_string(pSubRes->GetExpires());
        EventCallback(MkSipStatusOK, ExternHeads, MkSipContentNone, "");
    });
}

Uint32 CMkStateGridB::InviteRequestParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    MkString SdpBody = SipRequest.GetBody();
    MkString ChannelId = SipRequest.GetUri().GetUserName();
    MkString SessionId = SipRequest.GetDialogId();
    CMkSdp Sdp;
    Sdp.ParseContent(SdpBody);
    MkString RtpHost = Sdp.GetOrigin().GetAddr();
    if (!Sdp.GetConnection().GetAddr().empty()) {
        RtpHost = Sdp.GetConnection().GetAddr();
    }
    Uint16 RtpAudioPort = 0;
    Uint16 RtpVideoPort = 0;
    MkVector<CMkSdpMedia> VecSdpMedia = Sdp.GetMedia();
    MkVector<CMkSdpMedia>::iterator it = VecSdpMedia.begin();
    for (; it != VecSdpMedia.end(); it++) {
        if ("video" == it->GetMediaType()) {
            RtpVideoPort = it->GetPort();
        }
        if ("audio" == it->GetMediaType()) {
            RtpAudioPort = it->GetPort();
        }
    }
    if ((0 == RtpAudioPort && 0 == RtpVideoPort) || RtpHost.empty()) {
        return InvalidParams;
    }
    CMkStateGridBMediaRequest Req(SipRequest.GetFrom().GetUri().GetUserName(), ChannelId, SessionId, RtpHost, RtpAudioPort, RtpVideoPort);
    return m_Callback(&Req, [EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
        MkString strSdp;
        if (NoneError == ErrorCode) {
            const CMkStateGridBMediaResponse* pRes = dynamic_cast<const CMkStateGridBMediaResponse*>(pResBase);
            if (pRes) {
                strSdp = pRes->GetAnswerSdp();
            } else {
                ErrorCode = SystemError;
            }
        }
        EventCallback(NoneError == ErrorCode ? MkSipStatusOK : MkSipStatusBadRequest, MkMapString(), MkSipContentSdp, strSdp);
    });
}

Uint32 CMkStateGridB::SubscribeNotifyRequestParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    MkString RouterId = SipRequest.GetTo().GetUri().GetUserName();
    MkString DstId = SipRequest.GetUri().GetUserName();
    MkString SubscribeId = SipRequest.GetDialogId();
    MkStateGridBSubscribeType SubscribeType = MkStateGridBSubscribeEnd;
    MkString strEvent;
    MkString strState;
    Uint32 ErrorCode = SipRequest.GetHeaderValue("Event", strEvent);
    MkCheckErrorLog(ErrorCode, "get event header failed\n");

    ErrorCode = SipRequest.GetHeaderValue("Subscription-State", strState);
    MkCheckErrorLog(ErrorCode, "get expires header failed\n");

    tinyxml2::XMLDocument doc;
    ErrorCode = doc.Parse(SipRequest.GetBody().c_str());
    if (tinyxml2::XML_SUCCESS != ErrorCode) {
        return ErrorCode;
    }
    tinyxml2::XMLElement *Element = doc.FirstChildElement("SIP_XML");
    if (!Element) {
        return InvalidParams;
    }
    MkString EventType = CMkUtil::SafeMkString(Element->Attribute("EventType"));
    tinyxml2::XMLElement *ItemNode = Element->FirstChildElement("Item");
    MkString Name;
    Uint32 AlarmType = 0;
    CMkTime StartTime;
    CMkTime EndTime;
    MkString Code;
    Uint32 Status = 0;
    if ("Notify_Alarm" == EventType) {
        SubscribeType = MkStateGridBSubscribeAlarm;
        AlarmType = CMkUtil::SafeAtoi(ItemNode->Attribute("Type"));
        Name = CMkUtil::SafeMkString(ItemNode->Attribute("Name"));
        Code = CMkUtil::SafeMkString(ItemNode->Attribute("Code"));
        StartTime = CMkTime(CMkUtil::SafeMkString(ItemNode->Attribute("StartTime")), "T", "Z");
        EndTime = CMkTime(CMkUtil::SafeMkString(ItemNode->Attribute("EndTime")), "T", "Z");
        ErrorCode = NoneError;
    } else if ("Notify_Status" == EventType) {
        SubscribeType = MkStateGridBSubscribeStatus;
        Name = CMkUtil::SafeMkString(ItemNode->Attribute("Name"));
        Code = CMkUtil::SafeMkString(ItemNode->Attribute("Code"));
        Status = CMkUtil::SafeAtoi(ItemNode->Attribute("Status"));
        ErrorCode = NoneError;
    } else {
        ErrorCode = InvalidParams;
    }
    if (NoneError == ErrorCode) {
        CMkStateGridBSubscribeNotifyRequest Req(RouterId, DstId, SubscribeId, strState, SubscribeType, Code, Name, AlarmType, StartTime, EndTime, Status);
        return m_Callback(&Req, [this, EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
            EventCallback(NoneError == ErrorCode ? MkSipStatusOK : MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
        });
    }
    return ErrorCode;
}

Uint32 CMkStateGridB::ByeParse(const CMkSipMessage& SipRequest, const EventRequestCallback& EventCallback)
{
    MkString SessionId = SipRequest.GetDialogId();
    MkString RouterId = SipRequest.GetFrom().GetUri().GetUserName();
    MkString DstId = SipRequest.GetUri().GetUserName();
    CMkStateGridBMediaShutDownRequest Req(RouterId, DstId, SessionId);
    return m_Callback(&Req, [EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
        EventCallback(NoneError == ErrorCode ? MkSipStatusOK : MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
    });
}

Uint32 CMkStateGridB::MessageGetResouceRequestParse(const MkString& RouterId, const tinyxml2::XMLElement *pElement, const EventRequestCallback& EventCallback)
{
    CMkStateGridBGetResourseRequest Req(RouterId, pElement->Attribute("Code"), CMkUtil::SafeAtoi(pElement->Attribute("FromIndex")), CMkUtil::SafeAtoi(pElement->Attribute("ToIndex")));
    return m_Callback(&Req, [EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
        const CMkStateGridBGetResourceResponse *pRes = dynamic_cast<const CMkStateGridBGetResourceResponse*>(pResBase);
        if (!pRes || NoneError != ErrorCode) {
            EventCallback(MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
            return;
        }
        MkString strXml;
        tinyxml2::XMLDocument doc;
        doc.InsertFirstChild(doc.NewDeclaration());

        tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
        root->SetAttribute("EventType", "Response_Resource");
        doc.InsertEndChild(root);

        tinyxml2::XMLElement *SubListNode = doc.NewElement("SubList");
        SubListNode->SetAttribute("Code", pRes->GetParentId().c_str());
        SubListNode->SetAttribute("RealNum", std::to_string(pRes->GetRealNum()).c_str());
        SubListNode->SetAttribute("SubNum", std::to_string(pRes->GetSubNum()).c_str());
        SubListNode->SetAttribute("FromIndex", std::to_string(pRes->GetFromIndex()).c_str());
        SubListNode->SetAttribute("ToIndex", std::to_string(pRes->GetToIndex()).c_str());

        MkMapStateGridBResourse::const_iterator it = pRes->GetMapResource().begin();
        for (; it != pRes->GetMapResource().end(); it++) {
            tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
            ItemNode->SetAttribute("Code", it->second.Code.c_str());
            ItemNode->SetAttribute("Name", it->second.Name.c_str());
            ItemNode->SetAttribute("Status", std::to_string(it->second.Status).c_str());
            ItemNode->SetAttribute("DecoderTag", std::to_string(it->second.DecodeTag).c_str());
            ItemNode->SetAttribute("Longitude", std::to_string(it->second.Longitude).c_str());
            ItemNode->SetAttribute("Latitude", std::to_string(it->second.Latitude).c_str());
            ItemNode->SetAttribute("SubNum", std::to_string(it->second.SubNum).c_str());
            SubListNode->InsertEndChild(ItemNode);
        }
        root->InsertEndChild(SubListNode);
        tinyxml2::XMLPrinter printer;
        doc.Print(&printer);
        strXml = printer.CStr();
        EventCallback(MkSipStatusOK, MkMapString(), MkSipContentXml, strXml);
    });
}

Uint32 CMkStateGridB::MessageGetRecordRequestParse(const MkString& RouterId, const tinyxml2::XMLElement *pElement, const EventRequestCallback& EventCallback)
{
    CMkStateGridBFindRecordRequest Req(RouterId, pElement->Attribute("Code"), CMkUtil::SafeAtoi(pElement->Attribute("Type")), pElement->Attribute("UserCode"), CMkTime(pElement->Attribute("BeginTime")), CMkTime(pElement->Attribute("EndTime")), CMkUtil::SafeAtoi(pElement->Attribute("FromIndex")), CMkUtil::SafeAtoi(pElement->Attribute("ToIndex")));
    return m_Callback(&Req, [EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
        const CMkStateGridBGetRecordResponse* pRecordRes = dynamic_cast<const CMkStateGridBGetRecordResponse*>(pResBase);
        if (!pRecordRes || NoneError != ErrorCode) {
            EventCallback(MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
            return;
        }
        MkString strXml;
        tinyxml2::XMLDocument doc;
        doc.InsertFirstChild(doc.NewDeclaration());

        tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
        root->SetAttribute("EventType", "Response_History_Video");
        doc.InsertEndChild(root);

        tinyxml2::XMLElement *SubListNode = doc.NewElement("SubList");
        SubListNode->SetAttribute("RealNum", std::to_string(pRecordRes->GetRealNum()).c_str());
        SubListNode->SetAttribute("SubNum", std::to_string(pRecordRes->GetSubNum()).c_str());
        SubListNode->SetAttribute("FromIndex", std::to_string(pRecordRes->GetFromIndex()).c_str());
        SubListNode->SetAttribute("ToIndex", std::to_string(pRecordRes->GetToIndex()).c_str());

        MkVectorStateGridBRecord::const_iterator it = pRecordRes->GetVecRecord().begin();
        for (; it != pRecordRes->GetVecRecord().end(); it++) {
            tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
            ItemNode->SetAttribute("FileName", it->FileName.c_str());
            ItemNode->SetAttribute("FileUrl", it->RtspUrl.c_str());
            MkString StrTime;
            it->BeginTime.GetString(StrTime, "T", "Z");
            ItemNode->SetAttribute("BeginTime", StrTime.c_str());
            it->EndTime.GetString(StrTime, "T", "Z");
            ItemNode->SetAttribute("EndTime", StrTime.c_str());
            ItemNode->SetAttribute("Size", std::to_string(it->FileSize).c_str());
            ItemNode->SetAttribute("DecoderTag", std::to_string(it->DecoderTag).c_str());
            ItemNode->SetAttribute("Type", std::to_string(it->RecordType).c_str());
            SubListNode->InsertEndChild(ItemNode);
        }
        root->InsertEndChild(SubListNode);
        tinyxml2::XMLPrinter printer;
        doc.Print(&printer);
        strXml = printer.CStr();
        EventCallback(MkSipStatusOK, MkMapString(), MkSipContentXml, strXml);
    });
}

Uint32 CMkStateGridB::MessageGetAlarmRequestParse(const MkString& RouterId, const tinyxml2::XMLElement *pElement, const EventRequestCallback& EventCallback)
{
    CMkStateGridBGetAlarmRequest Req(RouterId, pElement->Attribute("Code"), CMkUtil::SafeAtoi(pElement->Attribute("Type")), pElement->Attribute("UserCode"), CMkTime(pElement->Attribute("BeginTime")), CMkTime(pElement->Attribute("EndTime")), CMkUtil::SafeAtoi(pElement->Attribute("Level")), CMkUtil::SafeAtoi(pElement->Attribute("FromIndex")), CMkUtil::SafeAtoi(pElement->Attribute("ToIndex")));
    return m_Callback(&Req, [EventCallback](Uint32 ErrorCode, const CMkStateGridBResponseBase* pResBase) {
        const CMkStateGridBGetAlarmResponse* pAlarmRes = dynamic_cast<const CMkStateGridBGetAlarmResponse*>(pResBase);
        if (!pAlarmRes || NoneError != ErrorCode) {
            EventCallback(MkSipStatusBadRequest, MkMapString(), MkSipContentNone, "");
            return;
        }
        MkString strXml;
        tinyxml2::XMLDocument doc;
        doc.InsertFirstChild(doc.NewDeclaration());

        tinyxml2::XMLElement *root = doc.NewElement("SIP_XML");
        root->SetAttribute("EventType", "Response_History_Alarm");
        doc.InsertEndChild(root);

        tinyxml2::XMLElement *SubListNode = doc.NewElement("SubList");
        SubListNode->SetAttribute("RealNum", std::to_string(pAlarmRes->GetRealNum()).c_str());
        SubListNode->SetAttribute("SubNum", std::to_string(pAlarmRes->GetSubNum()).c_str());
        SubListNode->SetAttribute("FromIndex", std::to_string(pAlarmRes->GetFromIndex()).c_str());
        SubListNode->SetAttribute("ToIndex", std::to_string(pAlarmRes->GetToIndex()).c_str());

        MkVectorStateGridBAlarm::const_iterator it = pAlarmRes->GetVecAlarm().begin();
        for (; it != pAlarmRes->GetVecAlarm().end(); it++) {
            tinyxml2::XMLElement *ItemNode = doc.NewElement("Item");
            ItemNode->SetAttribute("Code", it->Code.c_str());
            MkString StrTime;
            it->BeginTime.GetString(StrTime, "T", "Z");
            ItemNode->SetAttribute("BeginTime", StrTime.c_str());
            ItemNode->SetAttribute("Status", std::to_string(it->Status).c_str());
            ItemNode->SetAttribute("Type", std::to_string(it->AlarmType).c_str());
            SubListNode->InsertEndChild(ItemNode);
        }
        root->InsertEndChild(SubListNode);
        tinyxml2::XMLPrinter printer;
        doc.Print(&printer);
        strXml = printer.CStr();
        EventCallback(MkSipStatusOK, MkMapString(), MkSipContentXml, strXml);
    });
}

Uint32 CMkStateGridB::ResponseCallback(Uint32 ErrorCode, const MkString& strKey, const CMkStateGridBResponseBase* pRes)
{
    MkStateGridBResponseCallback ResCb;
    m_ReqLock.WLock();
#if 1
    MkDebugLog("get reqeust size:%d findkey:%s\n", m_MapRequst.size(), strKey.c_str());
    MkMap<MkString, MkSGARequestParam>::iterator itLoop = m_MapRequst.begin();
    for (; itLoop != m_MapRequst.end(); itLoop++) {
        MkDebugLog("get map request key:%s\n", itLoop->first.c_str());
    }
#endif
    MkMap<MkString, MkSGARequestParam>::iterator it = m_MapRequst.find(strKey);
    if (it != m_MapRequst.end()) {
        ResCb = it->second.ResCb;
        m_MapRequst.erase(it);
    }
    m_ReqLock.WUnlock();
    if (ResCb) {
        MkDebugLog("response code:%d\n", ErrorCode);
        ResCb(ErrorCode, pRes);
    }
    return NoneError;
}


Uint32 CMkStateGridB::DeleteRouter(const MkString& GbId)
{
    Uint32 ErrorCode = InvalidId;
    m_RouterLock.WLock();
    MkMap<MkString, MkStateGridBRouter>::iterator it = m_MapGbRouter.find(GbId);
    if (it != m_MapGbRouter.end()) {
        m_MapGbRouter.erase(it);
        ErrorCode = NoneError;
    }
    m_RouterLock.WUnlock();
    return ErrorCode;
}

Uint32 CMkStateGridB::GetRouter(const MkString& GbId, MkStateGridBRouter& Router)
{
    Uint32 ErrorCode = InvalidId;
    m_RouterLock.WLock();
    MkMap<MkString, MkStateGridBRouter>::iterator it = m_MapGbRouter.find(GbId);
    if (it != m_MapGbRouter.end()) {
        Router = it->second;
        ErrorCode = NoneError;
    }
    m_RouterLock.WUnlock();
    return ErrorCode;
}

Uint32 CMkStateGridB::AddReqeust(const MkString& strKey, const MkStateGridBResponseCallback& ResCb)
{
    m_ReqLock.WLock();
    MkSGARequestParam Param;
    Param.RequestTime = NowMkTime;
    Param.ResCb = ResCb;
    Param.StrKey = strKey;
    m_MapRequst[Param.StrKey] = Param;
    m_ReqLock.WUnlock();
    MkDebugLog("add request key:%s\n", strKey.c_str());
    return NoneError;
}

CMkStateGridB::~CMkStateGridB()
{
    Stop();
}